package com.love.marriage.datingRegistrationInfo.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.love.marriage.common.enums.DefaultAmountTypeEnum;
import com.love.marriage.common.enums.ResultEnum;
import com.love.marriage.common.enums.TransactionType;
import com.love.marriage.common.exceptions.SystemException;
import com.love.marriage.common.vo.SecurityUser;
import com.love.marriage.config.DefaultAmountConfig;
import com.love.marriage.datingInfo.service.DatingInfoService;
import com.love.marriage.datingInfo.vo.DatingInfoResVo;
import com.love.marriage.datingRegistrationInfo.entity.DatingRegistrationInfo;
import com.love.marriage.datingRegistrationInfo.mapper.DatingRegistrationInfoMapper;
import com.love.marriage.datingRegistrationInfo.service.DatingRegistrationInfoService;
import com.love.marriage.datingRegistrationInfo.vo.DatingRegistrationInfoExportVo;
import com.love.marriage.datingRegistrationInfo.vo.DatingRegistrationInfoVo;
import com.love.marriage.datingRegistrationInfo.vo.DatingSureRegistrationInfoVo;
import com.love.marriage.defaultAmountConfig.service.DefaultAmountConfigService;
import com.love.marriage.defaultAmountConfig.vo.DefaultAmountConfigVo;
import com.love.marriage.identityVerification.vo.IdentityVerificationVo;
import com.love.marriage.userActivityInfo.service.UserActivityInfoService;
import com.love.marriage.userActivityInfo.vo.UserActivityInfoVo;
import com.love.marriage.userBalanceInfo.service.UserBalanceInfoService;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoAddVo;
import com.love.marriage.userBalanceInfo.vo.UserBalanceInfoVo;
import com.love.marriage.userPartnerPreferences.mapper.UserPartnerPreferencesMapper;
import com.love.marriage.userPartnerPreferences.vo.UserPartnerPreferencesVo;
import com.love.marriage.userProfileInfo.vo.UserProfileInfoVo;
import com.love.marriage.utils.StringUtils;
import com.love.marriage.utils.UserUtils;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * description:  约会报名表服务实现类
 * author:       mybatisPlus
 * createDate:   2024-10-15 23:02:33
 * version:      1.0.0
 */
@Service
@RequiredArgsConstructor
public class DatingRegistrationInfoServiceImp extends ServiceImpl<DatingRegistrationInfoMapper, DatingRegistrationInfo> implements DatingRegistrationInfoService {

    private final DatingRegistrationInfoMapper datingRegistrationInfoMapper;

    private final DefaultAmountConfig defaultAmountConfig;

    private final UserBalanceInfoService userBalanceInfoService;

    private final DatingInfoService datingInfoService;

    private final DefaultAmountConfigService defaultAmountConfigService;

    private final UserActivityInfoService userActivityInfoService;

    private final UserPartnerPreferencesMapper userPartnerPreferencesMapper;

    @Override
    public Page<DatingRegistrationInfoVo> getPage(Long pageNum, Long pageSize, DatingRegistrationInfoVo datingRegistrationInfoVo) {
        Page<DatingRegistrationInfoVo> page = new Page<>(pageNum == null ? 1 : pageNum, pageSize == null ? 10 : pageSize);
        return datingRegistrationInfoMapper.getPage(page, datingRegistrationInfoVo);
    }

    @Override
    public DatingRegistrationInfoVo queryDatingRegistrationInfo(Long id) {
        return datingRegistrationInfoMapper.queryDatingRegistrationInfo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DatingRegistrationInfoVo addDatingRegistrationInfo(DatingRegistrationInfoVo datingRegistrationInfoVo) throws Exception {
        if (datingRegistrationInfoVo.getPayAmount() != null && BigDecimal.ZERO.compareTo(datingRegistrationInfoVo.getPayAmount()) > 0) {
            throw new Exception("支付金额不能小于0");
        }
        SecurityUser loginUser = UserUtils.getLoginUser();
        if (loginUser == null) {
            throw new SystemException(ResultEnum.USER_NO_LOGIN);
        }
        DatingInfoResVo datingInfoResVo = datingInfoService.queryDatingInfo(datingRegistrationInfoVo.getDatingId(), null, "");
        if (datingInfoResVo == null || LocalDateTime.now().isAfter(datingInfoResVo.getStartTime())) {
            throw new SystemException(ResultEnum.DATING_REGISTRY_OVER);
        }
        UserActivityInfoVo joinEvent = userActivityInfoService.queryUserActivityInfoByUser(datingRegistrationInfoVo.getUserId());
        if (joinEvent == null) {
            throw new SystemException(ResultEnum.USER_NOT_PROFILE_COMPLETE.getCode(), "请完善个人信息");
        }
//        UserProfileInfoVo userProfileInfoVo = userProfileInfoService.queryUserProfileInfoByUserId(datingRegistrationInfoVo.getUserId());
//        if (userProfileInfoVo == null) {
//            throw new SystemException(ResultEnum.USER_NOT_PROFILE_COMPLETE);
//        }
        // 如果存在则提示已报名
        LambdaQueryWrapper<DatingRegistrationInfo> query = Wrappers.<DatingRegistrationInfo>lambdaQuery().eq(DatingRegistrationInfo::getDatingId, datingRegistrationInfoVo.getDatingId())
                .eq(DatingRegistrationInfo::getUserId, datingRegistrationInfoVo.getUserId())
                .eq(DatingRegistrationInfo::getDeleteFlag, 0);
        DatingRegistrationInfo db = this.getOne(query);
        if (db != null) {
            throw new SystemException(ResultEnum.USER_ALREADY_JOIN_DATING);
        }
        UserBalanceInfoVo userBalanceInfoVo = userBalanceInfoService.queryUserBalanceInfoByUserId(datingRegistrationInfoVo.getUserId());
        DefaultAmountConfigVo defaultAmountConfigVo = defaultAmountConfigService.queryDefaultAmountConfigByCode(DefaultAmountTypeEnum.JOIN_DATING.getCode());
        BigDecimal paymentAmount;
        // 如果报名金额不为空则使用报名金额，否则查看默认配置表中是否有值，最后查询配置表中配置金额
        if (datingRegistrationInfoVo.getPayAmount() != null) {
            paymentAmount = datingRegistrationInfoVo.getPayAmount();
        } else if (defaultAmountConfigVo != null) {
            paymentAmount = defaultAmountConfigVo.getAmount();
        } else {
            paymentAmount = defaultAmountConfig.getEvent();
        }
        if (BigDecimal.ZERO.compareTo(paymentAmount) < 0 && (userBalanceInfoVo == null ||
                userBalanceInfoVo.getBalance().compareTo(paymentAmount) < 0)) {
            throw new SystemException(ResultEnum.USER_NO_ENOUGH_BALANCE);
        }
        if (datingRegistrationInfoVo.getRegistrationTime() == null) {
            datingRegistrationInfoVo.setRegistrationTime(LocalDateTime.now());
        }
        DatingRegistrationInfo datingRegistrationInfo = new DatingRegistrationInfo();
        BeanUtils.copyProperties(datingRegistrationInfoVo, datingRegistrationInfo);
        if (datingRegistrationInfo.getPayAmount() == null) {
            datingRegistrationInfo.setPayAmount(paymentAmount);
        }
        datingRegistrationInfoMapper.insert(datingRegistrationInfo);
        UserBalanceInfoAddVo userBalanceInfoAddVo = new UserBalanceInfoAddVo();
        userBalanceInfoAddVo.setUserId(datingRegistrationInfoVo.getUserId());
        userBalanceInfoAddVo.setAmount(paymentAmount);
        if (BigDecimal.ZERO.compareTo(paymentAmount) < 0) {
            userBalanceInfoService.reduceAmount(userBalanceInfoAddVo, datingRegistrationInfo.getId(), TransactionType.JOIN_DATING.getCode(), "应邀");
        }
        DatingRegistrationInfoVo res = new DatingRegistrationInfoVo();
        BeanUtils.copyProperties(datingRegistrationInfo, res);
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DatingRegistrationInfoVo addDatingRegistrationInfoBack(DatingRegistrationInfoVo datingRegistrationInfoVo) throws Exception {
        DatingInfoResVo datingInfoResVo = datingInfoService.queryDatingInfo(datingRegistrationInfoVo.getDatingId(), null, "");
        if (datingInfoResVo == null || LocalDateTime.now().isAfter(datingInfoResVo.getStartTime())) {
            throw new SystemException(ResultEnum.DATING_OVER);
        }
        UserActivityInfoVo joinEvent = userActivityInfoService.queryUserActivityInfoByUser(datingRegistrationInfoVo.getUserId());
        if (joinEvent == null) {
            throw new SystemException(ResultEnum.USER_NOT_PROFILE_COMPLETE.getCode(), "请完善个人信息");
        }
        // 如果存在则提示已报名
        LambdaQueryWrapper<DatingRegistrationInfo> query = Wrappers.<DatingRegistrationInfo>lambdaQuery()
                .eq(DatingRegistrationInfo::getDatingId, datingRegistrationInfoVo.getDatingId())
                .eq(DatingRegistrationInfo::getUserId, datingRegistrationInfoVo.getUserId())
                .eq(DatingRegistrationInfo::getDeleteFlag, 0);
        DatingRegistrationInfo db = this.getOne(query);
        if (db != null) {
            throw new SystemException(ResultEnum.USER_ALREADY_JOIN_DATING);
        }
        if (datingRegistrationInfoVo.getRegistrationTime() == null) {
            datingRegistrationInfoVo.setRegistrationTime(LocalDateTime.now());
        }
        DatingRegistrationInfo datingRegistrationInfo = new DatingRegistrationInfo();
        BeanUtils.copyProperties(datingRegistrationInfoVo, datingRegistrationInfo);
        datingRegistrationInfoMapper.insert(datingRegistrationInfo);
        DatingRegistrationInfoVo res = new DatingRegistrationInfoVo();
        BeanUtils.copyProperties(datingRegistrationInfo, res);
        return res;
    }

    @Override
    public DatingRegistrationInfoVo updateDatingRegistrationInfo(DatingRegistrationInfoVo datingRegistrationInfoVo) {
        DatingRegistrationInfo datingRegistrationInfo = new DatingRegistrationInfo();
        BeanUtils.copyProperties(datingRegistrationInfoVo, datingRegistrationInfo);
        datingRegistrationInfoMapper.updateById(datingRegistrationInfo);
        return datingRegistrationInfoVo;
    }

    @Override
    public DatingRegistrationInfoVo sureDating(DatingSureRegistrationInfoVo datingSureRegistrationInfoVo) {
        // 查询约会信息
        DatingInfoResVo datingInfoResVo = datingInfoService.queryDatingInfo(datingSureRegistrationInfoVo.getDatingId(), 
                        datingSureRegistrationInfoVo.getDatingUserId(), "detail");
        if (datingInfoResVo == null) {
            throw new SystemException(ResultEnum.DATING_NOT_EXIST);
        }
        // 查询约会报名信息
        List<DatingRegistrationInfoVo> datingRegistrationInfoVos = datingInfoResVo.getDatingRegistrationInfoVos();
        if (datingRegistrationInfoVos == null || datingRegistrationInfoVos.isEmpty()) {
            throw new SystemException(ResultEnum.DATING_NO_JOIN);
        }
        // 查找约会报名信息中是否存在状态为2的报名信息
        boolean isExist = datingRegistrationInfoVos.stream().anyMatch(item -> item.getStatus().equals("2"));
        if (isExist) {
            throw new SystemException(ResultEnum.DATING_ALREADY_SURE);
        }
        // 查找约会报名信息中是否存在datingSureRegistrationInfoVo中的userId的报名信息
        DatingRegistrationInfoVo datingRegistrationInfoVo = datingRegistrationInfoVos.stream().filter(item -> item.getUserId().equals(datingSureRegistrationInfoVo.getUserId())).findFirst().orElse(null);
        if (datingRegistrationInfoVo == null) {
            throw new SystemException(ResultEnum.DATING_NO_JOIN);
        }
        // 更新约会报名信息状态为2
        datingRegistrationInfoVo.setStatus("2");
        return updateDatingRegistrationInfo(datingRegistrationInfoVo);
    }

    @Override
    public Boolean deleteDatingRegistrationInfo(String ids) {
        if (StringUtils.isEmpty(ids)) {
            return true;
        }
        List<String> idArr = Arrays.asList(ids.split(","));
        datingRegistrationInfoMapper.deleteBatchIds(idArr);
        return true;
    }

    @Override
    public void exportDatingRegistrationInfo(DatingRegistrationInfoVo datingRegistrationInfoVo, HttpServletResponse response) throws Exception {
        List<DatingRegistrationInfoVo> list = datingRegistrationInfoMapper.getList(datingRegistrationInfoVo);
        List<DatingRegistrationInfoExportVo> res = list.stream().map(item -> {
            DatingRegistrationInfoExportVo datingRegistrationInfoExportVo = new DatingRegistrationInfoExportVo();
            datingRegistrationInfoExportVo.setDatingId(item.getDatingId());
            if (item.getDatingInfoVo() != null) {
                datingRegistrationInfoExportVo.setDatingContent(item.getDatingInfoVo().getContent());
                datingRegistrationInfoExportVo.setDatingTime(item.getDatingInfoVo().getStartTime());
            }
            if (item.getUserInfoVo() != null) {
                datingRegistrationInfoExportVo.setCode(item.getUserInfoVo().getCode());
                datingRegistrationInfoExportVo.setPhone(item.getUserInfoVo().getPhone());
            }
            if (item.getUserProfileInfoVo() != null) {
                UserProfileInfoVo userProfileInfoVo = item.getUserProfileInfoVo();
                datingRegistrationInfoExportVo.setNickname(userProfileInfoVo.getNickname());
                String genderName = null;
                if (userProfileInfoVo.getGender() != null) {
                    switch (userProfileInfoVo.getGender()) {
                        case "0":
                            genderName = "男";
                            break;
                        case "1":
                            genderName = "女";
                            break;
                        default:
                            genderName = "未知";
                    }
                }
                datingRegistrationInfoExportVo.setGender(genderName);
                if (userProfileInfoVo.getBirthYearMonth() != null) {
                    int age = Period.between(userProfileInfoVo.getBirthYearMonth(), LocalDate.now()).getYears();
                    datingRegistrationInfoExportVo.setAge(age);
                }
                datingRegistrationInfoExportVo.setWeight(userProfileInfoVo.getWeight());
                datingRegistrationInfoExportVo.setHeight(userProfileInfoVo.getHeight());
                datingRegistrationInfoExportVo.setProfessionName(userProfileInfoVo.getProfessionName());
                datingRegistrationInfoExportVo.setIncomeStatusName(userProfileInfoVo.getIncomeStatusName());
                String region = "";
                if (userProfileInfoVo.getProvinceName() != null) {
                    region += userProfileInfoVo.getProvinceName() + "/";
                }
                if (userProfileInfoVo.getCityName() != null) {
                    region += userProfileInfoVo.getCityName() + "/";
                }
                if (userProfileInfoVo.getDistrictName() != null) {
                    region += userProfileInfoVo.getCityName() + "/";
                }
                if (region.endsWith("/")) {
                    region = region.substring(0, region.length() - 1);
                }
                datingRegistrationInfoExportVo.setRegion(region);
            }
            if (item.getIdentityVerificationVo() != null) {
                IdentityVerificationVo identityVerificationVo = item.getIdentityVerificationVo();
                datingRegistrationInfoExportVo.setName(identityVerificationVo.getName());
                datingRegistrationInfoExportVo.setIdCardNumber(identityVerificationVo.getIdCardNumber());
            }
            // 追加：按用户ID关联导出“择偶要求”
            if (item.getUserId() != null) {
                UserPartnerPreferencesVo pref = userPartnerPreferencesMapper.queryUserPartnerPreferencesByUserId(item.getUserId());
                if (pref != null) {
                    datingRegistrationInfoExportVo.setPrefAgeFrom(pref.getAgeFrom());
                    datingRegistrationInfoExportVo.setPrefAgeTo(pref.getAgeTo());
                    datingRegistrationInfoExportVo.setPrefHeightFrom(pref.getHeightFrom());
                    datingRegistrationInfoExportVo.setPrefHeightTo(pref.getHeightTo());
                    datingRegistrationInfoExportVo.setPrefWeightFrom(pref.getWeightFrom());
                    datingRegistrationInfoExportVo.setPrefWeightTo(pref.getWeightTo());
                    datingRegistrationInfoExportVo.setPrefEducationLevel(pref.getEducationLevelName());
                    datingRegistrationInfoExportVo.setPrefProfession(pref.getProfessionName());
                    datingRegistrationInfoExportVo.setPrefIncomeRange(pref.getIncomeRangeName());
                    datingRegistrationInfoExportVo.setPrefHousingCarStatus(pref.getHousingCarStatusName());
                    datingRegistrationInfoExportVo.setPrefMaritalStatus(pref.getMaritalStatusName());

                    String prefRegion = "";
                    if (pref.getProvinceName() != null) {
                        prefRegion += pref.getProvinceName() + "/";
                    }
                    if (pref.getCityName() != null) {
                        prefRegion += pref.getCityName() + "/";
                    }
                    if (pref.getDistrictName() != null) {
                        prefRegion += pref.getDistrictName() + "/";
                    }
                    if (prefRegion.endsWith("/")) {
                        prefRegion = prefRegion.substring(0, prefRegion.length() - 1);
                    }
                    datingRegistrationInfoExportVo.setPrefProvinceName(pref.getProvinceName());
                    datingRegistrationInfoExportVo.setPrefCityName(pref.getCityName());
                    datingRegistrationInfoExportVo.setPrefDistrictName(pref.getDistrictName());
                    datingRegistrationInfoExportVo.setPrefRegion(prefRegion);
                }
            }
            datingRegistrationInfoExportVo.setRegistrationTime(item.getRegistrationTime());
            datingRegistrationInfoExportVo.setPayAmount(item.getPayAmount());
            return datingRegistrationInfoExportVo;
        }).collect(Collectors.toList());
        exportDatingRegistrationData(res, response);
    }

    public void exportDatingRegistrationData(List<DatingRegistrationInfoExportVo> registrationInfoVoList, HttpServletResponse response) throws Exception {
        // 设置导出参数
        ExportParams exportParams = new ExportParams("约会名单信息", "约会名单");

        // 生成 Excel
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, DatingRegistrationInfoExportVo.class, registrationInfoVoList);

        // 设置响应头
        // 设置返回类型为excel
        response.setContentType("application/vnd.ms-excel; charset=UTF-8");
        // 设置返回文件名为filename.xls
        response.setHeader("Content-Disposition", "filename.xls");
        // 请求或响应消息不能走缓存
        response.setHeader("Cache-Control", "no-cache");
        // 将Content-Disposition暴露出去，这样就可以用过JS获取到了
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        // 将 Excel 写入响应输出流并刷新缓冲区
        workbook.write(response.getOutputStream());
        response.flushBuffer(); // 确保数据完全写出
        workbook.close();
    }
}
